package com.uziot.bucket.shiro.config;

import com.uziot.bucket.shiro.dao.domain.SysUser;
import com.uziot.bucket.shiro.dao.mapper.SysMenuMapper;
import com.uziot.bucket.shiro.dao.mapper.SysRoleMapper;
import com.uziot.bucket.shiro.dao.mapper.SysUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Set;

/**
 * @author shidt
 * @version V1.0
 * @className JWTToken
 * @date 2020-11-16 23:48:56
 * @description 自定义实现 ShiroRealm，包含认证和授权两大模块
 */
@Slf4j
@Service("shiroRealm")
public class ShiroRealm extends AuthorizingRealm {
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    /**
     * 授权模块，获取用户角色和权限
     *
     * @param principals 身份信息
     * @return 权限信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = principals.toString();
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        SysUser sysUser = sysUserMapper.selectUserByUserName(username);
        // 获取用户角色集
        Set<String> roleSet = sysRoleMapper.selectUserRoles(username);
        simpleAuthorizationInfo.setRoles(roleSet);
        // 获取用户权限集
        Long userId = sysUser.getUserId();
        Set<String> permissionSet = sysMenuMapper.selectMenuPermsByUserId(userId);
        simpleAuthorizationInfo.setStringPermissions(permissionSet);
        return simpleAuthorizationInfo;
    }

    /**
     * 用户认证
     *
     * @param authenticationToken 身份认证 token
     * @throws AuthenticationException 认证相关异常
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 这里的 token是从 JWTFilter 的 executeLogin 方法传递过来的，已经经过了解密
        String token = (String) authenticationToken.getCredentials();
        // 获取token,token暂时使用username
        if (token == null) {
            throw new AuthenticationException("token invalid");
        }

        if (!StringUtils.isEmpty(token)) {
            return new SimpleAuthenticationInfo(token, token, "shiroRealm");
        }
        throw new AuthenticationException("Token expired or incorrect.");

    }


}
